忍者刘米米

14. Inheritance

Defining a Base Class

  • Any class that does not inherit from another class is known as a base class.
  • Swift classes do not inherit from a universal base class. Classes you define without specifying a superclass automatically become base classes for you to build upon.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "traveling at \(currentSpeed) miles per hour"
}
func makeNoise() {
// do nothing - an arbitrary vehicle doesn't necessarily make a noise
}
}

let someVehicle = Vehicle()

print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour

Subclassing

Subclassing is the act of basing a new class on an existing class. The subclass inherits characteristics from the existing class, which you can then refine. You can also add new characteristics to the subclass.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class SomeSubclass: SomeSuperclass {
// subclass definition goes here
}

class Bicycle: Vehicle {
var hasBasket = false
}

let bicycle = Bicycle()
bicycle.hasBasket = true

bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour

class Tandem: Bicycle {
var currentNumberOfPassengers = 0
}

let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: \(tandem.description)")
// Tandem: traveling at 22.0 miles per hour

Overriding

A subclass can provide its own custom implementation

Accessing Superclass Methods, Properties, and Subscripts

  • calling super.someMethod()within the overriding method implementation.
  • super.someProperty within the overriding getter or setter implementation.
  • super[someIndex] from within the overriding subscript implementation.

Overriding Methods

1
2
3
4
5
6
7
8
9
class Train: Vehicle {
override func makeNoise() {
print("Choo Choo")
}
}

let train = Train()
train.makeNoise()
// Prints "Choo Choo"

Overriding Properties

  • provide your own custom getter and setter for that property
  • add property observers to enable the overriding property

Overriding Property Getters and Setters

property Custom Getter Custom Setter
Inherited stored yes yes
Inherited computed yes yes
  • custom getter (and setter,) to override any inherited property( stored or computed property.
  • subclass only know inherited property has a certain name and type.
  • Must state name and type in subclass to check .
  • You can present an inherited read-only property as a read-write property by providing both a getter and a setter in your subclass property override. You cannot, however, present an inherited read-write property as a read-only property.
  • If you have setter for override , then you must have getter for it.
1
2
3
4
5
6
7
8
9
10
11
12
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear \(gear)"
}
}

let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \(car.description)")
// Car: traveling at 25.0 miles per hour in gear 3

Overriding Property Observers

  • add property observers to an inherited property. This enables you to be notified when the value of an inherited property changes
  • You cannot add property observers to inherited constant stored properties or inherited read-only computed properties.
  • Note also that you cannot provide both an overriding setter and an overriding property observer for the same property. If you want to observe changes to a property’s value, and you are already providing a custom setter for that property, you can simply observe any value changes from within the custom setter.
1
2
3
4
5
6
7
8
9
10
11
12
class AutomaticCar: Car {
override var currentSpeed: Double {
didSet {
gear = Int(currentSpeed / 10.0) + 1
}
}
}

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4

Preventing Overrides

  • final var, final func, final class func, and final subscript
  • Methods, properties, or subscripts that you add to a class in an extension can also be marked as final within the extension’s definition.
  • You can mark an entire class as final by writing the final modifier before the class keyword in its class definition (final class).